home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- File: MyExceptionHandler.c
-
- By: R. Mark Fleming Think C V3.02 Signal Routines....
-
- EMail: flemingm@QUCDN.QueensU.CA
- Phone: (613) 545-9732 (h), (613) 545-2039 (w)
- SMail: 521 Albert Street
- Kingston, Ont.
- Canada, K7K 4M5
-
- Description: This is modelled after Apple's MPW's exception handler/
- Signals routines that are in it's sample code...
-
- Note: I have uses the same Prototyping as Apple routines (in fact they
- are a copy of apple's prototype def's).
-
- Creation Date: January 31, 1990
-
- special note:
- I have not tested these routines very well, but they did work to
- compile Apple's "AppleTalk GetZoneList Sample Application", so use at
- your own risk...
-
- You may use, modify and redistribute BUT NOT SELL this code provided
- that all changes/bug fixes are returned to the author for inclusion.
-
- ************************************************************************/
-
- #include <asm.h>
-
- typedef struct {
- long regs[11]; /* D3-D7/A2-A7 */
- short error;
- long message;
- long failA6;
- long failPC;
- Ptr nextInfo; /* Handler */
- long whoPC; /* Next FI structure */
- short whatSignals;
- /* this is used to keep the old stack frame return address */
- long sigFRet;
- } FailInfo, *PFailInfo;
-
- /* Call the following initialization routine before your other initializations (InitGraf, etc.)-
- in other words as early as you can in the application. */
-
- extern pascal void InitUFailure();
- /* Allocates the heap block for CatchSignals and initializes the global
- variables used by the unit. C programs must use this instead of InitSignals. */
-
- extern pascal void Signal(short);
- /* Returns control to the point of the last CatchSignal/CatchFailures. The program will
- then behave as though that CatchSignal had returned with the code parameter
- supplied to Signal. If CatchCFailures is catching, the message parameter will be 0. */
-
- extern pascal void SignalMessage(short, long);
- /* Returns control to the point of the last CatchSignal.
- If CatchCFailures is catching, the message parameter will be returned. */
-
- extern pascal void CatchCFailures(/* FailInfo *, ProcPtr */);
- /* Call this to set up an exception handler. This pushes your handler onto
- a stack of exception handlers. */
-
- extern pascal void Failure(/* short, long */);
- /* Call this to signal a failure. Control will branch to the most recent
- exception handler, which will be popped off the handler stack. */
-
- extern pascal void Success(FailInfo *);
- /* Call this when you want to de-install your exception handler (pop 1
- element off the handler stack). */
-
- /*********************************************************/
-
- static FailInfo *Sig;
-
- /*********************************************************/
-
- pascal void InitUFailure()
- /* Allocates the heap block for CatchSignals and initializes the global
- variables used by the unit. No CatchSignals from the main level
- of Pascal are allowed if you use InitUFailure.
- [C programs must use this instead of InitSignals.] */
- {
- Sig = 0L;
- }
-
- /* Note: CatchCFailures() has 2 parameters, but to stop Think C from creating
- LINK A6 code, they are left out....
- */
- pascal void CatchCFailures()
- /* Call this to set up an exception handler. This pushes your handler onto
- a stack of exception handlers. */
- { asm {
- MOVE.L (A7)+,D2 ; Return Address
- MOVE.L (A7)+,d0 ; Handler address
- MOVE.L (A7)+,A0 ;fi
- MOVEM.L A2-A7/D3-D7,(A0) ; save Reg. & Restored Stack pointer.
- CLR.W OFFSET(FailInfo,error)(a0)
- CLR.L OFFSET(FailInfo,message)(a0)
- MOVE.L Sig,D1 ;Add this Record to Link List.
- MOVE.L a0,Sig
- MOVE.L D1,OFFSET(FailInfo,whoPC)(a0)
- MOVE.L D0,OFFSET(FailInfo,nextInfo)(a0) ;Clean Up routine to call..
- MOVE.L D2,OFFSET(FailInfo,sigFRet)(a0) ;Save Return Address..
-
- MOVE.L D2,A0 ;get return address
- JMP (A0)
- }
- }
-
- pascal void Failure()
- /*
- int error;
- long message;
- Call this to signal a failure. Control will branch to the most recent
- exception handler, which will be popped off the handler stack. */
- { /* DebugStr("\pFailure"); */
- asm {
- MOVE.L Sig,A0
- move.l a0,d0
- bne.s @1
- move.l (a7)+,a0 ;Get Return Address
- move.l (a7)+,d0 ;Pop message off stack
- move.w (a7)+,d0 ;Pop error off Stack
- jmp (a0) ; Return to caller.
- @1
- move.l (a7)+,OFFSET(FailInfo,failPC)(a0) ;Pop Old Return Address
- MOVEM.L (A0),A2-A7/D3-D7 ;Restore Old Registers..
-
- MOVE.L OFFSET(FailInfo,nextInfo)(a0),a1 ;Get Clean Routine
- move.l a1,d0
- BEQ.s @2
- jsr (a1) ;Call if not NULL
- @2
- MOVE.L Sig,A0
- MOVE.w OFFSET(FailInfo,error)(a0),d0 ;Set Return Code!!! to Error
- MOVE.L OFFSET(FailInfo,whoPC)(a0),d1 ;Pop off Stack.
- MOVE.L d1,Sig ;ie. Remove from Link List.
- MOVE.L OFFSET(FailInfo,sigFRet)(a0),a0 ;Goto catch place...
- jmp (a0)
-
- }
- }
-
- pascal void Success(fi)
- FailInfo *fi;
- /* Call this when you want to de-install your exception handler
- (pop 1 element off the handler stack). */
- {
- if (Sig) Sig = (FailInfo *) Sig->whoPC; /* Pop Off Stack */
- }
-
- pascal void SignalMessage(code, message)
- int code;
- long message;
- {
- Failure(code, message);
- Debugger(); /* Should never Reach this... */
- }
-
- pascal void Signal(code)
- int code;
- {
- if (code) {
- Failure(code, 0);
- Debugger();
- }
- }